package com.qsl.ssyx.payment.service.impl;

import com.github.wxpay.sdk.WXPayUtil;
import com.qsl.ssyx.common.constant.RedisConst;
import com.qsl.ssyx.common.exception.BusinessException;
import com.qsl.ssyx.common.result.Result;
import com.qsl.ssyx.common.result.ResultCodeEnum;
import com.qsl.ssyx.enums.PaymentStatus;
import com.qsl.ssyx.model.order.PaymentInfo;
import com.qsl.ssyx.payment.config.WXPaymentConfig;
import com.qsl.ssyx.payment.service.PaymentInfoService;
import com.qsl.ssyx.payment.service.WXPaymentService;
import com.qsl.ssyx.payment.utils.HttpClient;
import com.qsl.ssyx.vo.user.UserLoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

@Service
public class WXPaymentServiceImpl implements WXPaymentService {

    @Autowired
    private PaymentInfoService paymentInfoService;
    @Autowired
    private RedisTemplate redisTemplate;

    //    微信支付-JSAPI
    @Override
    public Map<String, String> createJsapi(String orderNo) {
        // 根据商品唯一id查询支付记录表是否有此订单
        PaymentInfo paymentInfo = paymentInfoService.getPaymentInfoByOrderNo(orderNo);
        if (paymentInfo == null) {
            // 根据orderNo（订单号）查询订单信息,并根据订单信息新增订单支付表-支付记录表新增订单
            paymentInfo = paymentInfoService.savePaymentInfo(orderNo);
        }

        // 2 封装微信支付系统接口需要的参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", WXPaymentConfig.APPID); // 公众账号ID
        paramMap.put("mch_id", WXPaymentConfig.PARTNER); // 微信支付，服务号商家id
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());  // 随机字符串，不长于32位
        paramMap.put("body", paymentInfo.getSubject());  // 商品描述:
        paramMap.put("out_trade_no", paymentInfo.getOrderNo()); // 商户订单号
//        int totalFee = paymentInfo.getTotalAmount().multiply(new BigDecimal(100)).intValue();
//        paramMap.put("total_fee", String.valueOf(totalFee));
        paramMap.put("total_fee", "1"); // 支付金额,单位为分，  此处0.01
        paramMap.put("spbill_create_ip", "127.0.0.1"); // 用户终端IP
        paramMap.put("notify_url", WXPaymentConfig.NOTIFYURL); // 支付成功后微信调用的地址 后端项目接口-用于接收支付成功或失败的回调信息。在用户发起支付请求后，微信服务器会将支付结果异步发送到该URL地址，商户需要对接收到的支付结果进行处理，例如生成订单、更新订单状态等。通常情况下，notify_url由商户在微信支付平台上进行配置，并保证能够正确响应微信服务器的请求
        paramMap.put("trade_type", "JSAPI"); //支付类型： ①付款码支付，②JSAPI支付，③Native支付，④App支付，⑤H5支付，⑥小程序支付，⑦刷脸支付
        UserLoginVo userLoginVo = (UserLoginVo) redisTemplate.
                opsForValue().get(RedisConst.USER_LOGIN_KEY_PREFIX + paymentInfo.getUserId());
        // 用户的openid
        if (userLoginVo != null && StringUtils.isEmpty(userLoginVo.getUserId())) {
            paramMap.put("openid", userLoginVo.getOpenId());
        } else {
            paramMap.put("openid", "odo3j4q2KskkbbW-krfE-cAxUnzU1"); // 管理员的openid,正常使用上面的
        }
        //  调用微信支付接口-返回packae(prepay_id)

        try {
            // 通过httpclient调用微信支付接口
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");  // HttpClientUtils
            // 转成xml格式
            String xmlParam = WXPayUtil.generateSignedXml(paramMap, WXPaymentConfig.PARTNERKEY); // 商户key
            client.setXmlParam(xmlParam);// 转成xml
            client.setHttps(true);   // 注意：API请求必须使用HTTPS
            client.post();  // 发送post请求

            // 微信支付接口返回的数据，注意：返回xml格式
            String xml = client.getContent();
            System.out.println("======> xml: " + xml);
            Map<String, String> resultMap = WXPayUtil.xmlToMap(xml); // xml 转 map
            // 判断是否支付成功
            if (resultMap.get("result_code") == null && !resultMap.get("result_code").equals("SUCCESS")) {
                System.out.println("error1" + resultMap);
                throw new BusinessException(ResultCodeEnum.PAYMENT_FAIL);
            }

            // 封装数据-包括预付单标识，package(prepay_id)
            Map<String, String> parameterMap = new HashMap<>();
            parameterMap.put("appId", WXPaymentConfig.APPID);// 公众号id
            parameterMap.put("nonceStr", resultMap.get("nonce_str"));  // 随机字符串，不长于32位
            String prepayId = String.valueOf(resultMap.get("prepay_id"));
            String packages = "prepay_id=" + prepayId;
            parameterMap.put("package", packages);  // 必须返回如下格式：prepay_id=***
            parameterMap.put("signType", "MD5"); // 签名类似： ①MD5(默认)  ②HMAC-SHA256  ③RSA
            parameterMap.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); // 从 1970 年 1 月 1 日 00:00:00 至今的秒数，即当前的时间
            String sign = WXPayUtil.generateSignature(parameterMap, WXPaymentConfig.PARTNER); //签名. 商户key

            // 封装返回数据
            Map<String, String> result = new HashMap();
            result.put("timeStamp", parameterMap.get("timeStamp"));  // 从 1970 年 1 月 1 日 00:00:00 至今的秒数，即当前的时间
            result.put("nonceStr", parameterMap.get("nonceStr")); // 随机字符串，长度为32个字符以下
            result.put("signType", "MD5"); // 签名算法
            result.put("paySign", sign); // 签名
            result.put("package", packages); // 统一下单接口返回的 prepay_id 参数值，提交格式如：prepay_id=***

            return result;
        } catch (Exception e) {
            throw new BusinessException(ResultCodeEnum.PAYMENT_FAIL);
        }
    }

    //  根据订单号调用微信接口查询支付状态
    @Override
    public Map<String, String> queryPayStatus(String orderNo) {
        // 封装数据
        Map paramMap = new HashMap();
        paramMap.put("appid", WXPaymentConfig.APPID);
        paramMap.put("mch_id", WXPaymentConfig.PARTNER); //  商户号
        paramMap.put("out_trade_no", orderNo); // 订单号
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr()); // 获取随机字符串

        // post请求微信接口
        HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
        try {
            client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, WXPaymentConfig.PARTNERKEY)); // 商户key
            client.setHttps(true);   // 注意：API请求必须使用HTTPS
            client.post();  // 发送post请求

            // 获取返回结果
            String xml = client.getContent();
            Map<String, String> stringMap = WXPayUtil.xmlToMap(xml);// xml 转map
            return stringMap;
        } catch (Exception e) {
            throw new BusinessException(ResultCodeEnum.DATA_ERROR);
        }
    }

    //  支付成功： 修改支付记录状态（已经支付），修改订单记录（减库存）
    @Override
    public void paySuccess(String outTradeNo, Map<String, String> resultMap) {
        // 根据订单号查询当前订单信息
        PaymentInfo paymentInfo = paymentInfoService.getPaymentInfoByOrderNo(outTradeNo);
        //判断是否支付成功
        if (paymentInfo.getPaymentStatus() != PaymentStatus.UNPAID) { // 支付中
            return;
        }

        // 修该支付记录表的支付状态
        paymentInfo.setPaymentStatus(PaymentStatus.PAID); // 已支付
        paymentInfo.setTradeNo(resultMap.toString()); // 交易编号
        paymentInfoService.updateById(paymentInfo);

        // TOTO 整合RabbitMQ修改订单支付状态、库存
        return;

    }


    // 支付中,等待  ==>  定时器，每隔3秒查询是否支付成功
    @Override
    public void payTimer()  {
//        Timer timer = new Timer();
//        timer.schedule(new TimerTask() {
//            //最大重试次数
//            int max_retry = 5;
//
//            @Override
//            public void run() {
//
//                max_retry--; // 次数减1
//
//                //
//
//
//            }
//
//        }, 2000, 5);
//        throw new BusinessException(ResultCodeEnum.PAYMENT_WAITING);
    }


}
